import re

from qturboframe.lib.webdriver.exceptions import SeleniumError
from qturboframe.lib.utils.by import By

from .base_element import BaseElement

class Select(BaseElement):
    '''
    Jres2.0 的下拉选择框

    :Attributes:
     - _driver: 控件所在的当前webdriver对象
     - _elements: 单选按钮元素列表，list
     - timeout: 步骤操作的超时时间

    :Example:
     - 例1: Select(webelement)
     - 例2: Select({By.CLASS_NAME:'class_name','text':'文本信息'})
     - 例3: Select({By.CLASS_NAME:'class_name','text':'文本信息'}, father=driver)
     - 例4: Select({By.CLASS_NAME:'class_name','text':'文本信息'}, father=webelement)
    '''

    def __init__(self, element_para, father=None, timeout=5):
        super().__init__(element_para, father, timeout)

    def set_value_for_single(self, value):
        """
        jres2.0的单选下拉框选择

        :Args:
         - value: 选择项的文本

        :Example:
         - 例: select.set_value_for_single("text")
        """
        text = None
        if isinstance(value, list):
            text = value[0]
        else:
            text = value
            
        text_list = re.findall(r'[^\r\n]+', self._element.text)

        li_xpath = "./li[not(contains(@style,'display: none'))]"
        labels = self._element.find_elements_by_attribute('xpath',li_xpath, timeout=self.timeout)
        index = text_list.index(text)
        BaseElement(labels[index]).click()

    def __get_li_tag_by_text(self, text, index=1):
        li_tag = None
        li_clicked_tag = None
        for element in self._elements:
            if not element.is_displayed():
                continue

            li_span_xpath = ".//li[not(contains(normalize-space(@style),'display: none')) and not(contains(normalize-space(@style),'display:none'))]//span[normalize-space(text())='{}']".format(
                text)
            li_span_tags = element.find_displayed_elements(By.XPATH, li_span_xpath, timeout=0.2)
            if len(li_span_tags) != 0:
                li_tag = li_span_tags[index-1].find_element_by_attribute(By.XPATH, ".//ancestor::li[1]",
                                                                       timeout=self.timeout)
                # 找到a tag
                a_tag = li_span_tags[index-1].exist(By.XPATH, ".//ancestor::a[1]", timeout=0.1)
                if a_tag:
                    li_clicked_tag = a_tag
                else:
                    li_clicked_tag = li_span_tags[index-1]
            else:
                li_a_xpath = ".//li//a[contains(normalize-space(text()),'{}')]".format(text)
                li_a_tags = element.find_elements_by_attribute(By.XPATH, li_a_xpath, timeout=0.2)
                if len(li_a_tags) != 0:
                    li_clicked_tag = li_a_tags[index-1]
                    li_tag = li_a_tags[index-1].find_element_by_attribute(By.XPATH, ".//ancestor::li[1]",
                                                                        timeout=self.timeout)
                else:
                    li_xpath = ".//li[contains(normalize-space(text()),'{}')]".format(text)
                    li_tags = element.find_elements_by_attribute(By.XPATH, li_xpath, timeout=0.2)
                    if len(li_tags) != 0:
                        li_clicked_tag = li_tags[index-1]
                        li_tag = li_tags[index-1]

            if li_tag:
                break

        return (li_clicked_tag, li_tag)

    def select_value_by_text(self, text, index=1, is_check_open = False):
        """
        依次根据li/span/a，li/span或者li中的文字查找对应的li标签

        :Args:
         - text: li标签中的文字
         - is_check_open: 当li元素具有某个class时，则不执行点击动作， 例如当菜单已经展开，则不再点击菜单

        :Example:
         - 例: select.select_value_by_text("text")
        """
        li_clicked_tag, li_tag = self.__get_li_tag_by_text(text, index)

        if li_tag:
            if not ("active" in li_tag.get_attribute("class") and is_check_open):
                BaseElement(li_clicked_tag).click()

        if not li_tag:
            raise SeleniumError("找不到li中文字为:“{}”的元素".format(text))

        return li_tag

    def select_tree_node_by_text(self, text, index=1):
        """
        依次根据li/span/a，li/span或者li中的文字查找对应的li标签

        :Args:
         - text: li标签中的文字
         - is_check_open: 当li元素具有某个class时，则不执行点击动作， 例如当菜单已经展开，则不再点击菜单

        :Example:
         - 例: select.select_tree_node_by_text("text")
        """
        li_clicked_tag, li_tag = self.__get_li_tag_by_text(text, index)

        if li_tag:
            # 在tree的li标签中有一个class为switch的标签，标识此tree节点是否被打开
            #当class为swtich的span标签，此外还具有noline_docuclass时，此按钮是不可见，不可被点击的
            switch_tag = li_tag.exist(By.XPATH,"./span[contains(@class,'switch') and not(contains(@class,'noline_docu'))]", timeout=0.1)
            switch_tag_class=''
            if switch_tag:
                li_clicked_tag = switch_tag
                switch_tag_class = switch_tag.get_attribute("class")
            if 'noline_open' not in switch_tag_class:
                BaseElement(li_clicked_tag).click()
        else:
            raise SeleniumError("找不到li中文字为:“{}”的元素".format(text))

        return li_tag

    # def select_value_by_text(self, text, index=0, is_check_open = False):
    #     """
    #     依次根据li/span/a，li/span或者li中的文字查找对应的li标签
    #
    #     :Args:
    #      - text: li标签中的文字
    #      - is_check_open: 当li元素具有某个class时，则不执行点击动作， 例如当菜单已经展开，则不再点击菜单
    #
    #     :Example:
    #      - 例: select.select_value_by_text("text")
    #     """
    #     li_tag = None
    #     for element in self._elements:
    #         if not element.is_displayed():
    #             continue
    #
    #         li_span_xpath = ".//li[not(contains(normalize-space(@style),'display: none')) and not(contains(normalize-space(@style),'display:none'))]//span[contains(normalize-space(text()),'{}')]".format(text)
    #         li_span_tags = element.find_elements_by_attribute(By.XPATH, li_span_xpath, timeout=0.2)
    #         if len(li_span_tags)!=0:
    #             li_tag = li_span_tags[index].find_element_by_attribute(By.XPATH, ".//ancestor::li[1]", timeout=self.timeout)
    #             #找到a tag
    #             a_tag = li_span_tags[index].exist(By.XPATH,".//ancestor::a[1]", timeout=0.1)
    #             if a_tag:
    #                 li_clicked_tag = a_tag
    #             else:
    #                 li_clicked_tag = li_span_tags[index]
    #         else:
    #             li_a_xpath = ".//li//a[contains(normalize-space(text()),'{}')]".format(text)
    #             li_a_tags = element.find_elements_by_attribute(By.XPATH, li_a_xpath, timeout=0.2)
    #             if len(li_a_tags)!=0:
    #                 li_clicked_tag = li_a_tags[index]
    #                 li_tag = li_a_tags[index].find_element_by_attribute(By.XPATH, ".//ancestor::li[1]", timeout=self.timeout)
    #             else:
    #                 li_xpath = ".//li[contains(normalize-space(text()),'{}')]".format(text)
    #                 li_tags = element.find_elements_by_attribute(By.XPATH, li_xpath, timeout=0.2)
    #                 if len(li_tags)!=0:
    #                     li_clicked_tag =li_tags[index]
    #                     li_tag = li_tags[index]
    #
    #         if li_tag:
    #             if not ("active" in li_tag.get_attribute("class") and is_check_open):
    #                 BaseElement(li_clicked_tag).click()
    #             break
    #
    #     if not li_tag:
    #         raise SeleniumError("找不到li中文字为:“{}”的元素".format(text))
    #
    #     return li_tag


    def set_value_for_multiple(self, value=['all']):
        """
        jres2.0的多选下拉框选择

        :Args
         - value: 选择项的文本，list类型

        :Example:
         - 例1: select.set_value_for_multiple()
         - 例2: select.set_value_for_multiple("Text")
         - 例3: select.set_value_for_multiple("Text1/Text2")
        """
        num = 0
        lis = self._element.find_elements_by_attribute('css selector', 'li[style="display: block;"]',
                                            timeout=self.timeout)
        # 选择前先全部清空
        for li in lis:
            li.focus()
            if "h_cur" in li.get_attribute('class'):
                BaseElement(li.find_element_by_attribute('xpath', './label')).click()
        # 勾选
        if len(value) == 1 and value[0] == 'all':
            for li in lis:
                li.focus()
                li.find_element_by_attribute('xpath', './label').secure_click()
            num += len(lis)
        else:
            labels = self._element.find_elements_by_attribute('css selector', 'li[style="display: block;"]>label',
                                                   timeout=self.timeout)
            text_list = re.findall(r'[^\r\n]+', self._element.text)
            for text in value:
                index = text_list.index(text)
                labels[index].focus()
                BaseElement(labels[index]).click()
                # labels[index].secure_click()
                num += 1
        return num

    def get_all_li_texts(self):
        """
        获取ul下所有li的内容

        :Args:
         - text: li标签中的文字
         - is_check_open: 当li元素具有某个class时，则不执行点击动作， 例如当菜单已经展开，则不再点击菜单

        :Example:
         - 例: select.select_value_by_text("text")
        """
        li_tags = None
        li_span_xpath = ".//li[not(contains(normalize-space(@style),'display: none')) and not(contains(normalize-space(@style),'display:none'))]//span"
        li_span_tags = self._element.find_elements_by_attribute(By.XPATH, li_span_xpath, timeout=0.2)
        if len(li_span_tags) != 0:
            li_tags = li_span_tags
        else:
            li_a_xpath = ".//li//a"
            li_a_tags = self._element.find_elements_by_attribute(By.XPATH, li_a_xpath, timeout=0.2)
            if len(li_a_tags) != 0:
                li_tags = li_a_tags
            else:
                li_xpath = ".//li"
                li_tags = self._element.find_elements_by_attribute(By.XPATH, li_xpath, timeout=0.2)

        li_tag_text_list = []
        for li_tag in li_tags:
            li_tag.location_once_scrolled_into_view
            if BaseElement(li_tag).get_text() !='' and li_tag.is_displayed():
                li_tag_text_list.append(BaseElement(li_tag).get_text().strip())

        #如果没有找到信息则查找div中的信息
        if len(li_tag_text_list)==0:
            li_span_xpath = ".//li[not(contains(normalize-space(@style),'display: none')) and not(contains(normalize-space(@style),'display:none'))]//div"
            li_span_tags = self._element.find_elements_by_attribute(By.XPATH, li_span_xpath, timeout=0.2)
            for li_tag in li_span_tags:
                li_tag.location_once_scrolled_into_view
                if BaseElement(li_tag).get_text() != '' and li_tag.is_displayed():
                    li_tag_text_list.append(BaseElement(li_tag).get_text().strip())

        return li_tag_text_list